#include "StdAfx.h"
#include "DropDownUI.h"
#include "ControlUI.h"
#include "BlueRenderEngineUI.h"
#include "DropDownWnd.h"

CDropDownUI::CDropDownUI(void):m_iCurSel(-1), 
m_uButtonState(0)
{
	m_szDropBox = CStdSize(0, 150);
	::ZeroMemory(&m_rcButton, sizeof(RECT));
}

CDropDownUI::~CDropDownUI(void)
{
}

LPCTSTR CDropDownUI::GetClass() const
{
	return _T("DropDownUI");
}

LPVOID CDropDownUI::GetInterface(LPCTSTR pstrName)
{
	if( _tcscmp(pstrName, _T("ListOwner")) == 0 ) return static_cast<IListOwnerUI*>(this);
	return CContainerUI::GetInterface(pstrName);
}

UINT CDropDownUI::GetControlFlags() const
{
	return UIFLAG_TABSTOP;
}

void CDropDownUI::Init()
{
	if( m_iCurSel < 0 ) SelectItem(0);
}

int CDropDownUI::GetCurSel() const
{
	return m_iCurSel;
}

bool CDropDownUI::SelectItem(int iIndex)
{
	if( iIndex == m_iCurSel ) return true;
	if( m_iCurSel >= 0 ) {
		CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]);
		IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
		if( pListItem != NULL ) pListItem->Select(false);
		m_iCurSel = -1;
	}
	if( m_items.GetSize() == 0 ) return false;
	if( iIndex < 0 ) iIndex = 0;
	if( iIndex >= m_items.GetSize() ) iIndex = m_items.GetSize() - 1;
	CControlUI* pControl = static_cast<CControlUI*>(m_items[iIndex]);
	if( !pControl->IsVisible() ) return false;
	if( !pControl->IsEnabled() ) return false;
	IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
	if( pListItem == NULL ) return false;
	m_iCurSel = iIndex;
	pControl->SetFocus();
	pListItem->Select(true);
	if( m_pManager != NULL ) m_pManager->SendNotify(pControl, _T("itemclick"));
	if( m_pManager != NULL ) m_pManager->SendNotify(this, _T("itemselect"));
	Invalidate();
	return true;
}

bool CDropDownUI::Add(CControlUI* pControl)
{
	IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
	if( pListItem != NULL ) {
		pListItem->SetOwner(this);
		pListItem->SetIndex(m_items.GetSize());
	}
	return CContainerUI::Add(pControl);
}

bool CDropDownUI::Remove(CControlUI* pControl)
{
	ASSERT(!"Not supported");
	return false;
}

void CDropDownUI::RemoveAll()
{
	m_iCurSel = -1;
	CContainerUI::RemoveAll();
}

void CDropDownUI::Event(TEventUI& event)
{
	if( event.Type == UIEVENT_BUTTONDOWN && IsEnabled() )
	{
		Activate();
		m_uButtonState |= UISTATE_PUSHED | UISTATE_CAPTURED;
	}
	if( event.Type == UIEVENT_MOUSEMOVE )
	{
		if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {
			if( ::PtInRect(&m_rcButton, event.ptMouse) ) m_uButtonState |= UISTATE_PUSHED;
			else m_uButtonState &= ~UISTATE_PUSHED;
			Invalidate();
		}
	}
	if( event.Type == UIEVENT_BUTTONUP )
	{
		if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {
			m_uButtonState &= ~(UISTATE_PUSHED | UISTATE_CAPTURED);
			Invalidate();
		}
	}
	if( event.Type == UIEVENT_KEYDOWN )
	{
		switch( event.chKey ) {
	  case VK_F4:
		  Activate();
		  return;
	  case VK_UP:
		  SelectItem(FindSelectable(m_iCurSel - 1, false));
		  return;
	  case VK_DOWN:
		  SelectItem(FindSelectable(m_iCurSel + 1, true));
		  return;
	  case VK_PRIOR:
		  SelectItem(FindSelectable(m_iCurSel - 10, false));
		  return;
	  case VK_NEXT:
		  SelectItem(FindSelectable(m_iCurSel + 10, true));
		  return;
	  case VK_HOME:
		  SelectItem(FindSelectable(0, false));
		  return;
	  case VK_END:
		  SelectItem(FindSelectable(GetCount() - 1, true));
		  return;
		}
	}
	if( event.Type == UIEVENT_SCROLLWHEEL )
	{
		bool bDownward = LOWORD(event.wParam) == SB_LINEDOWN;
		SelectItem(FindSelectable(m_iCurSel + (bDownward ? 1 : -1), bDownward));
		return;
	}
	CControlUI::Event(event);
}

bool CDropDownUI::Activate()
{
	if( !CControlUI::Activate() ) return false;
	CDropDownWnd* pWindow = new CDropDownWnd;
	pWindow->Init(this);
	if( m_pManager != NULL ) m_pManager->SendNotify(this, _T("dropdown"));
	Invalidate();
	return true;
}

CStdString CDropDownUI::GetText() const
{
	if( m_iCurSel < 0 ) return _T("");
	CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]);
	return pControl->GetText();
}

SIZE CDropDownUI::GetDropDownSize() const
{
	return m_szDropBox;
}

void CDropDownUI::SetDropDownSize(SIZE szDropBox)
{
	m_szDropBox = szDropBox;
}

void CDropDownUI::SetPos(RECT rc)
{
	// Put all elements out of sight
	RECT rcNull = { 0 };
	for( int i = 0; i < m_items.GetSize(); i++ ) static_cast<CControlUI*>(m_items[i])->SetPos(rcNull);
	// Position this control
	CControlUI::SetPos(rc);
}

SIZE CDropDownUI::EstimateSize(SIZE /*szAvailable*/)
{
	SIZE sz = { 0, 12 + m_pManager->GetThemeFontInfo(UIFONT_NORMAL).tmHeight };
	// Once there is an element in the list, we'll use the first one to
	// determine the size of the dropdown base control.
	if( m_cxyFixed.cx > 0 && !m_items.IsEmpty() ) {
		RECT rcText = m_rcItem;
		::InflateRect(&rcText, -4, -2);
		sz = static_cast<CControlUI*>(m_items[0])->EstimateSize(CStdSize(rcText.right - rcText.left, 0));
	}
	return sz;
}

void CDropDownUI::DoPaint(HDC hDC, const RECT& rcPaint)
{
	// Paint the nice frame
	int cy = m_rcItem.bottom - m_rcItem.top;
	::SetRect(&m_rcButton, m_rcItem.right - cy, m_rcItem.top, m_rcItem.right, m_rcItem.bottom);
	RECT rcText = { m_rcItem.left, m_rcItem.top, m_rcButton.left + 1, m_rcItem.bottom };
	if( !IsEnabled() ) {
		CBlueRenderEngineUI::DoPaintFrame(hDC, m_pManager, rcText, UICOLOR_CONTROL_BORDER_DISABLED, UICOLOR__INVALID, UICOLOR__INVALID);
	}
	else {
		CBlueRenderEngineUI::DoPaintFrame(hDC, m_pManager, rcText, UICOLOR_CONTROL_BORDER_NORMAL, UICOLOR_CONTROL_BORDER_NORMAL, UICOLOR__INVALID);
	}
	// Paint dropdown edit box
	::InflateRect(&rcText, -1, -1);
	if( m_iCurSel >= 0 ) {
		CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]);
		IListItemUI* pElement = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
		if( pElement != NULL ) {
			// Render item with specific draw-style
			pElement->DrawItem(hDC, rcText, UIDRAWSTYLE_INPLACE | (m_bFocused ? UIDRAWSTYLE_FOCUS : 0));
		}
		else {
			// Allow non-listitems to render as well.
			RECT rcOldPos = pControl->GetPos();
			pControl->SetPos(rcText);
			pControl->DoPaint(hDC, rcText);
			pControl->SetPos(rcOldPos);
		}
	}
	else {
		CBlueRenderEngineUI::DoFillRect(hDC, m_pManager, rcText, UICOLOR_CONTROL_BACKGROUND_NORMAL);
	}
	// Paint dropdown button
	RECT rcPadding = { 0 };
	CBlueRenderEngineUI::DoPaintButton(hDC, m_pManager, m_rcButton, _T("<i 6>"), rcPadding, m_uButtonState, 0);
}

